增量引擎串讲.md•8.54 kB
# 增量引擎串讲
## 目录
1. [增量引擎](#增量引擎)
- [什么是增量引擎/增量更新](#-什么是增量引擎增量更新)
- [核心概念](#-核心概念)
- [增量更新概要流程图](#-增量更新概要流程图)
2. [基于增量引擎的UI Demo](#基于增量引擎的ui-demo)
- [UI demo](#ui-demo)
- [创建流程](#创建流程)
- [更新流程](#更新流程)
---
## 增量引擎
### - 什么是增量引擎/增量更新
增量引擎可以理解为: 在 UI/树形结构的重建过程中,精准追踪“哪里改变了”,只重算和重建“受影响”的局部,而不是整棵树全量重建。目标是把每一帧的更新成本由全量降为“受影响子集”
**插入wiki中图片**
### - 核心概念
- Scope(记忆化作用域) **待加入原wiki中的补充**
- 由 `getMemoScope` 在某个父作用域下按调用点哈希 `id` 创建/复用。
- 保存上次计算值、子作用域与挂接的 `IncrementalNode`,并跟踪依赖。
- 关键字段/行为:`recomputeNeeded`、`isUnchanged()`、`recache(newValue)`、`invalidate()`。
- State(可变状态)
- 抽象类 `AbstractState` 及实现 `StateImpl`;亦包含参数状态 `ParameterImpl`(函数形参被包成 State 以可追踪)。
- 读时登记依赖,写时置 `updateNeeded = true` 并在快照阶段比较 `snapshot` 与 `current` 判定 `modified`。
- Dependency(依赖追踪)
- 在作用域/状态被“读取”时,通过 `manager.getDependency()` 注册到 `Dependencies`,用于之后精准失效/增量重算。
- IncrementalNode(增量节点)
- 双向链 + `incrementalRef` 指针。提供 `incrementalUpdateSkip(count)` 快速跳过未变更子树;在 `incrementalUpdateDone(parent)` 中完成插入/连接与一致性校验。
- Manager(状态管理器)
- `StateManagerImpl` 是运行时核心:持有 `currentScope`、`createdStates`、`dirtyScopes`、`updateNeeded` 等;提供根装配 `updatableNode`、快照推进 `updateSnapshot()`、以及作用域构造 `getMemoScope(...)`。
### - 增量更新概要流程图(参考“详解.md”的讲解方式)
```text
外部触发(创建为例)
└─ memoRoot/updatableNode 建立根 Scope+Node(冻结)
└─ 执行 update(被 Memo/MemoIntrinsic 注入)
├─ manager.getMemoScope 获取/创建子 Scope
├─ scope.param 包装形参为 State(登记依赖)
├─ scope.isUnchanged?
│ ├─ 是 → scope.getCached(登记依赖,节点跳过)
│ └─ 否 → 计算 compute → scope.recache(更新缓存、断开失效子树、节点增量接入)
└─ 返回
状态改变(State.setValue)
└─ 标记 manager.updateNeeded = true
└─ 外部驱动 updateSnapshot() //下一帧,触发更新
├─ 遍历 createdStates:updateStateSnapshot 判定 modified
├─ 作用域 invalidate 冒泡到顶层,加入 dirtyScopes
└─ 消费 dirtyScopes:scope.isModified() → 必要时 getValue()/recache(仅受影响子树重算)
```
## 基于增量引擎的UI Demo
### UI demo
```
code here
```
### 创建流程
```
memoRoot(rootNode, update)
├─ GlobalStateManager.instance() → 返回 manager
├─ 创建 lambda1: { => manager.runWithFrozen(update) }
└─ updatableNode(rootNode, lambda1, None)
├─ 创建 lambda2: { => update(); node }
├─ 创建 lambda3: {_ => cleanup?()}
├─ ScopeImpl.init(None, 2, lambda2, lambda3, None)
│ ├─ super(None, 2)
│ ├─ this.myCompute = lambda2 [保存,不执行]
│ └─ this.myCleanup = lambda3 [保存,不执行]
├─ scope.param(0, lambda4, ...) [lambda4 保存,不执行]
├─ scope.param(1, lambda5, ...) [lambda5 保存,不执行]
└─ 返回 scope [根作用域创建完成]
```

### 更新流程
```
执行rootScope.getValue()
├─ ScopeImpl.getValue()
│ ├─ isUnchanged()
│ │ ├─ isRecomputeNeeded() → true
│ │ ├─ this.scopeInternal = manager.currentScope [保存]
│ │ ├─ manager.currentScope = this [切换]
│ │ └─ 返回 false
│ ├─ compute = this.myCompute.getOrThrow() [获取 lambda2]
│ └─ recache(compute()) [执行 lambda2]
│ ├─ 执行 lambda2: { => update(); node }
│ │ └─ 执行 update() [即 lambda1]
│ │ ├─ frozen = true
│ │ ├─ 执行 runnable(this) [即用户 update]
│ │ │ └─ NodeAttach(createA, updateA)
│ │ │ ├─ getMemoScope(...) [创建子作用域]
│ │ │ ├─ createA() → 创建 nodeA [执行 create lambda]
│ │ │ ├─ updateA(nodeA) [执行 update lambda]
│ │ │ │ └─ counter.getValue()
│ │ │ │ └─ counter.onAccess() [登记依赖]
│ │ │ └─ recache(nodeA)
│ │ └─ frozen = old
│ │ └─ 返回 node
│ ├─ manager.currentScope = this.scopeInternal [恢复]
│ ├─ this.myValue = node
│ ├─ this.recomputeNeeded = false
│ ├─ detachChildScopes(None)
│ ├─ parent?.increment(...)
│ ├─ nodeAttached?.incrementalUpdateDone(...)
│ └─ getCached()
│ └─ 返回 node
└─ 返回 node
```
